/**
* File: Tournament.h
*
* \brief Tournament support code.
**/
#pragma once
#include "../engine.h"
#include "globals.h"

#include <string>
using namespace std;

namespace game{

#define TOURNAMENT_NUMBER_OF_TEAMS 2
#define TOURNAMENT_MAX_NUMBER_OF_ROUNDS 32

	/**
	* \class Team
	* \brief A tournament team.
	**/
	class Team
	{
	public:
		/** Per round information **/
		typedef struct Round_s
		{
			/** Whether it is CT or T **/
			CounterStrikeTeams::Enumeration team;
			/** Enemy kills count **/
			int nEnemyKills;
			/** 
			* Whether the objective was achieved. 
			* For CTs, objective is met iff: (1) All Ts are killed; (2) Bomb is defused
			* For Ts, objective is met iff: (1) All CTs are killed; (2) Target is bombed
			**/
			bool wasObjectiveAchieved;
			bool enemyRaisedException;
			/** Remaining time in case of successfull objective completion **/
			float remainingTime;
			/** Round score **/
			float score;
		} Round;

		/** The team name (dll path) **/
		string name;
		/** Team per round information **/
		Round rounds[TOURNAMENT_MAX_NUMBER_OF_ROUNDS];
		/** Final score **/
		float score;
	};

	/**
	* \class Tournament
	* \brief The tournament.
	*
	* \author Instituto Superior Tecnico de Lisboa, Portugal
	* \author Technical University of Lisbon, Portugal
	* 
	* \author Agentes Autonomos e Sistemas Multiagente
	* \author Autonomous Agents and Multiagent Systems
	* 
	* \version	1.0
	* \date		2006/2007
	**/
	class Tournament{
	public:
		Tournament();

		/** 
		* \brief Whether the tournament is running.
		**/
		bool isOn(){ return _isOn; }

		void load(char* file);
		void initialize();
		void newRound();

		bool isTournamentMaster(){ return _isTournamentMaster; }
		void handleEnemyKill(edict_t* killer, edict_t* victim);
		void handleObjectiveAchieved(CounterStrikeTeams::Enumeration team, bool enemyRaisedException=false);
		void handleException(bool mastersException);

		void update();

		/** 
		* \brief Whether a new round can start.
		**/
		bool readyForNewRound;

	private:
		void forceNewRound();
		void readTeams();
		void determineWhetherIsTournamentMaster();
		void setupRoundTeams();
		void resolveStats();
		void saveSummary();
		void saveTxtSummary(FILE* sOut, char* timeStr);
		void saveXmlSummary(FILE* sOut, char* timeStr, char* dateStr);
		void conclude();
		int getTeamIndex(){ if(isTournamentMaster())return 0; else return 1; }
		Team* getTeam(){ return &_teams[getTeamIndex()]; }
		Team* getTeam(CounterStrikeTeams::Enumeration victoriousTeam);

		/** 
		* \brief Whether tournament mode is active.
		**/
		bool _isOn;
		/** 
		* \brief Score per goal achievement.
		**/
		int _scoreForGoal;
		/** 
		* \brief Score per enemy kill.
		**/
		int _scorePerKill;
		/** 
		* \brief Score per remaining second in case of goal achievement.
		**/
		int _scorePerRemainingSecond;
		/** 
		* \brief Number of rounds in the tournament.
		**/
		int _roundCount;
		/** 
		* \brief Number of agents per team.
		**/
		int _agentsPerTeam;
		/** 
		* \brief Whether this agent version is the tournament master. 
		*
		* The tournament master is responsible for keeping score and saving the score summary.
		**/
		bool _isTournamentMaster;
		/** 
		* \brief Current tournament round.
		**/
		int _currentRound;
		/** 
		* \brief The teams.
		**/
		Team _teams[TOURNAMENT_NUMBER_OF_TEAMS];

		/** 
		* \brief Whether to ignore an apparent goal achievement.
		**/
		bool _ignoreAchievedObjective;
		/** 
		* \brief Whether to force a new round.
		**/
		bool _forceNewRound;
		/** 
		* \brief Time to start a new round.
		**/
		float _timeToStartNewRound;
	};

	/** 
	* \brief The tournament.
	**/
	extern Tournament g_tournament;
}
